
#ifndef __USKELETON_H__
#define __USKELETON_H__

#include "typedefs.h"
#include <vector>
#include <map>

using namespace std;

/// Defines an unhierarchical skeleton
class USkeleton {
   
public:
   USkeleton();
   USkeleton(const char *filename);
   USkeleton(const vector<Point3> &j, const vector<vector<int> > &g);
   
   int nBones() { return bones.size(); }
   int nJoints() { return joints.size(); }
   
   const Point3& joint(int i) const { return joints[i]; }
   const Point3& getJointPos(int i) const { return joints[i]; }
   const Segment3 boneSegment(int i) const;
   void setJointPos(int i, const Point3 &p) { joints[i]=p; }
   /// Translate the joint i 
   void translateJoint(int i, const Vector3 &t);
   /// Inserts a new element at the end and returns an identifier for the element
   int addJoint(const Point3 &p);
   /// Inserts a bone between the joints i and j
   void addBone(int i, int j);
   
   void setRelatedParamBone(int i, const pair<Number, int>&prm) { relatedParam[i]=prm; }
   const pair<Number, int>& getRelatedParamBone(int i) const { return relatedParam[i]; }
   
   /// Export the skeleton in SKE format
   void export_ske(const char *filename);
   /// Export the skeleton in SKEL format
   void export_skel(const char *filename);
   static USkeleton* load(const char *filename);
   
   Vector3 getBoneProjector(const Point3 &v, const int idbone);
   float getDistance(const Point3 &v, const int idbone, float t);
   
   /// Initializes auxiliar structures used for clustering purposes
   void resetAuxiliarVars();
   
   /// prints the bones ids
   void printBones();
   /// prints the branches
   void printBranches();
   /// prints the bones in PREV format
   void printBonesPREV();
   
private:
   void genBonesList();
   
   /// Generates the branch list for a uskeleton
   void genBranches();
   ///
   void getBranch(int id);
   ///
   bool isJunction(int id) {
      return (graph[id].size() > 2);
   }
   bool isTerminal(int id) {
      return (graph[id].size() == 1);
   }
public:
   
   vector<Point3>             joints; // the array of joints
   vector<pair<int, int> >    bones;
   vector<vector<int> >       graph; // A table that represents the squeleton's connectivity
   vector<pair<Number, int> > relatedParam; // A table with parameters of a bone for each joint
   vector<int>                prev; // describes the bones using a "previous format": bone = [jointId, jointPrevId]
   
   // rigging variables
   vector<int>                closest_vertex; // the closest vertex id
   vector<Number>             min_distance_vertex; // the distance to the closest vertex
   vector<bool>               onlyvisible; // o closetvisible bone predomina sobre o bone
                                          //  mais proximo na metrica que inclui um caminho ao longo da superficie

   vector<vector<int> >       branches; // the array of branches of the skeleton
   
protected:
   
   vector<int>  branch;
   vector<bool> ismarked; // auxiliar array used for the branches generation process
};

#endif
